﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.ComponentModel.Composition;

using ETRobocon.RaceTraking.GamePresentation;
using ETRoboConTrakingSystem;

namespace ETRobocon.RaceTraking.GameManagement
{
    /// <summary>
    /// TurnMgmtUserControl.xaml の相互作用ロジック
    /// </summary>
    public partial class TurnMgmtUserControl : UserControl
    {
        private enum RaceState
        {
            NotReady,
            Ready,
            Running,
            Finished
        }
        private RaceState _currentRaceState = RaceState.NotReady;

        private SwitchLightStatus _switchLightStatus;
        public SwitchLightStatus SwitchLightStatus
        {
            get { return _switchLightStatus; }
            set
            {
                _switchLightStatus = value;
            }
        }

        public ISwitchLightStatusNotifier switchLightStatusNotifier { get; set; }

        public WSRound CurrentRound
        {
            get { return this.Resources["targetRound"] as WSRound; }
        }

        public WSTeamEntry InCourseTeamEntry {
            get { return this.Resources["inCourseTeam"] as WSTeamEntry;}
        }

        public WSTeamEntry OutCourseTeamEntry {
            get { return this.Resources["outCourseTeam"] as WSTeamEntry;}
        }


        private WSRunner _inCourseRunner;
        private WSRunner _outCourseRunner;
        private IBonusCheckPointsBuilder _icBcpBuilder = null;
        private IBonusCheckPointsBuilder _ocBcpBuilder = null;
        private Window _ownerWindow;
        public Window OwnerWindow
        {
            set { _ownerWindow = value; }
        }

        private IRaceTrackingPresentation _presentationWindow;
        public IRaceTrackingPresentation PresentationWindow
        {
            set
            {
                _presentationWindow = value;
//                this.icRunnerConsole.PresentationMain = value.MainControl;
                this.icRunnerConsole.MainTimerCounter = value.MainTimerCounter;
                this.icRunnerConsole.PMRunnerStatus = value.InCourseRunnerStatus;
                this.icRunnerConsole.CourseName = WSRunner.CourseName.IN;
                this.icRunnerConsole.PresentationMain = value;

//                this.ocRunnerConsole.PresentationMain = value.MainControl;
                this.ocRunnerConsole.MainTimerCounter = value.MainTimerCounter;
                this.ocRunnerConsole.PMRunnerStatus = value.OutCourseRunnerStatus;
                this.ocRunnerConsole.CourseName = WSRunner.CourseName.OUT;
                this.ocRunnerConsole.PresentationMain = value;

  //              _icBcpBuilder.PresentationMain = value;
    //            _ocBcpBuilder.PresentationMain = value;

            //    this.icRunnerConsole.OwnerPanel = this;
            //    this.ocRunnerConsole.OwnerPanel = this;

                this.icRunnerConsole.RunnerStatusChanged += new RunnerStatusChangedEventHandler(InCourseRunnerConsole_RunnerStatusChanged);
                this.ocRunnerConsole.RunnerStatusChanged += new RunnerStatusChangedEventHandler(OutCourseRunnerConsole_RunnerStatusChanged);
          }
        }

        void InCourseRunnerConsole_RunnerStatusChanged(object sender, RunnerStatusChangedEventArgs args)
        {
            if (args.RunnerStatus == WSRunner.RunnerStatus.Obstructed)
            {
                ObstructedOperationUIEnabling();
            }
        }

        private void ObstructedOperationUIEnabling()
        {
            cbObstructedOperation.IsEnabled = true;
        }

        private void ObstructedOperationStart()
        {
            this.buttonTurnAgain.IsEnabled = true;
            this.buttonTurnLast.IsEnabled = true;
            this.buttonTurnDone.IsEnabled = false;
        }
        void OutCourseRunnerConsole_RunnerStatusChanged(object sender, RunnerStatusChangedEventArgs args)
        {
            if (args.RunnerStatus == WSRunner.RunnerStatus.Obstructed)
            {
                ObstructedOperationUIEnabling();
            }
        }

        [Import(typeof(IBonusCheckPointsBuilder), AllowRecomposition = true)]
        private Lazy<IBonusCheckPointsBuilder> _inCourseBCPBuilderExtension { get; set; }
        [Import(typeof(IBonusCheckPointsBuilder), AllowRecomposition = true)]
        private Lazy<IBonusCheckPointsBuilder> _outCourseBCPBuilderExtension { get; set; }

        public IBonusCheckPointsBuilder InCourseBCPBuilder
        {
            get
            {
                if (_icBcpBuilder == null)
                {
                    _icBcpBuilder = new BonusCheckPointsBuilder();
              //      _icBcpBuilder = _inCourseBCPBuilderExtension.Value;
                    //                    _icBcpBuilder = new BonusCheckPointsBuilder();
                    _icBcpBuilder.TargetCanvas = icRunnerConsole.canvasCourse;
                    _icBcpBuilder.TargetRunner = icRunnerConsole.CurrentRunner;
                    _icBcpBuilder.CheckMarkMgmtControls = icRunnerConsole.MyCheckMarkMgmtControls;
                }
                return _icBcpBuilder;
            }
        }

        public IBonusCheckPointsBuilder OutCourseBCPBuilder
        {
            get
            {
                if (_ocBcpBuilder == null)
                {
//                    _ocBcpBuilder = _outCourseBCPBuilderExtension.Value;
                    _ocBcpBuilder = new BonusCheckPointsBuilder();
//                    _ocBcpBuilder = new BonusCheckPointsBuilder();
                    _ocBcpBuilder.TargetCanvas = ocRunnerConsole.canvasCourse;
                    _ocBcpBuilder.TargetRunner = ocRunnerConsole.CurrentRunner;
                    _ocBcpBuilder.CheckMarkMgmtControls = ocRunnerConsole.MyCheckMarkMgmtControls;
                }
                return _ocBcpBuilder;
            }
        }

        public TurnMgmtUserControl()
        {
            InitializeComponent();
            this.Resources["inCourseTeam"] = this.tteUCIC.CurrentTeamEntry;
            this.Resources["outCourseTeam"] = this.tteUCOC.CurrentTeamEntry;
            this.icRunnerConsole.CurrentRunner.Course = WSRunner.CourseName.IN;
            this.ocRunnerConsole.CurrentRunner.Course = WSRunner.CourseName.OUT;

            this.tteUCIC.CurrentRunner = this.icRunnerConsole.CurrentRunner;
            this.tteUCOC.CurrentRunner = this.ocRunnerConsole.CurrentRunner;

            _inCourseRunner = this.tteUCIC.CurrentRunner;
            _outCourseRunner = this.tteUCOC.CurrentRunner;

            this.buttonNext.IsEnabled = true;
            this.ButtonVoice.IsEnabled = false;

           // LoadInCourseDifficultStatus();
        }

        public void LoadInCourseDifficultStatus()
        {
            icRunnerConsole.ActivateDifficultPointStatus();
            System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();

            string imgFileName = "Enigma";
            for (int i = 1; i <= 4; i++)
            {
                string source = this.GetType().Namespace + ".Imgs" + "." + imgFileName + i + ".png";
                System.IO.Stream imgStream = myAssembly.GetManifestResourceStream(source);
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = imgStream;
                bi.EndInit();
                icRunnerConsole.LoadImageToDifficultPointStatus(i, bi);
            }
        }

        public void RaceStart()
        {
        }

        public void RaceStop(int count)
        {
        }

        public void RunnerGoaled(WSRunner.CourseName course, int count)
        {
            if (course == WSRunner.CourseName.IN)
            {
                _inCourseRunner.RunTime = count;
                _inCourseRunner.Status = WSRunner.RunnerStatus.Completed;
            }
            else
            {
                _outCourseRunner.RunTime = count;
                _outCourseRunner.Status = WSRunner.RunnerStatus.Completed;
            }
        }
        public void RunnerRetired(WSRunner.CourseName course, int count)
        {
            if (course == WSRunner.CourseName.IN)
            {
                _inCourseRunner.Status = WSRunner.RunnerStatus.Retired;
            }
            else
            {
                _outCourseRunner.Status = WSRunner.RunnerStatus.Retired;
            }
        }
        public void RunnerBonusCleared(WSRunner.CourseName course, string bonusShortName, int count)
        {
            WSRunner runner = _inCourseRunner;
            if (course == WSRunner.CourseName.OUT)
            {
                runner = _outCourseRunner;
            }
            WSBonusResult br = runner.GetBonusResult(bonusShortName);
            if (br != null)
            {
                br.Cleared = true;
            }
        }

        private void buttonNext_Click(object sender, RoutedEventArgs e)
        {
            var rm = new ETRoboConTrakingSystem.ETRoboConRM.ETRoboConRaceMgmtClient();
//            using (WSRaceMgmt.RaceMgmt rm = new ETRobocon.RaceTraking.GameManagement.WSRaceMgmt.RaceMgmt())
            {
                int turnNo;
                int turnId;
                int icr;
                int ocr;
                if (rm.GetTurnInfo(out turnNo, out turnId,out icr,out ocr,CurrentRound.ID))// new Guid(CurrentRound.ID), out turnNo, out turnId, out icr, out ocr))
                {
                    WSTurn turn = this.Resources["currentTurn"] as WSTurn;
                    turn.ID = turnId;
                    if (turnNo == -1)
                    {
                        turn.No = null;
                        this.buttonEnd.IsEnabled = true;
                    }
                    else
                    {
                        turn.No = turnNo;
                        ButtonVoice.IsEnabled = true;
                    }
                    this._presentationWindow.CurrentRoundInfo.TurnNo = turn.No;

//                    WSRaceMgmt.TeamInfo teamInfo;
                    ETRoboConTrakingSystem.ETRoboConRM.TeamInfo teamInfo;
                    if (rm.GetTeamInfoByEntryTeam(out teamInfo, icr))// (icr, out teamInfo))
                    {
                        InCourseTeamEntry.ID = teamInfo.EntryTeamId;
                        InCourseTeamEntry.TeamID = teamInfo.TeamId;
                        InCourseTeamEntry.Name = "";
                        if (teamInfo.Exhibition == true)
                        {
                            InCourseTeamEntry.Name = "*";
                        }
                        InCourseTeamEntry.Name += teamInfo.Name;
                        InCourseTeamEntry.Bib = teamInfo.Bib;
                        turn.InCourseEntry = InCourseTeamEntry;

                        _inCourseRunner.Course = WSRunner.CourseName.IN;
                        _inCourseRunner.Status = WSRunner.RunnerStatus.Ready;
                        _inCourseRunner.Team = InCourseTeamEntry;
                        _inCourseRunner.Turn = turn;
                        _inCourseRunner.ClearResults();

                        icRunnerConsole.CurrentTurn = turn;

                        this._presentationWindow.CurrentInCourseRunnerInfo.Bib = teamInfo.Bib;
                        this._presentationWindow.CurrentInCourseRunnerInfo.TeamName = teamInfo.Name;
                    }
                    else
                    {
                        InCourseTeamEntry.ID = -1;
                        InCourseTeamEntry.TeamID = -1;
                        InCourseTeamEntry.Bib = null;
                        InCourseTeamEntry.Name = "";
                        turn.InCourseEntry = null;

                        _inCourseRunner.Team = InCourseTeamEntry;
                        this._presentationWindow.CurrentInCourseRunnerInfo.Bib = null;
                        this._presentationWindow.CurrentInCourseRunnerInfo.TeamName = "";
                    }
                    this._presentationWindow.CurrentInCourseRunnerInfo.RunTime = "";
                    this._presentationWindow.CurrentInCourseRunnerInfo.Point = "";
                    
                    this._presentationWindow.InCourseRunnerStatus.ResetClearedMarks();
                    
                    if (rm.GetTeamInfoByEntryTeam(out teamInfo,ocr))// (ocr, out teamInfo))
                    {
                        OutCourseTeamEntry.ID = teamInfo.EntryTeamId;
                        OutCourseTeamEntry.TeamID = teamInfo.TeamId;
                        OutCourseTeamEntry.Bib = teamInfo.Bib;
                        OutCourseTeamEntry.Name = "";
                        if (teamInfo.Exhibition != null && teamInfo.Exhibition == true)
                        {
                            OutCourseTeamEntry.Name = "*";
                        }
                        OutCourseTeamEntry.Name += teamInfo.Name;
                        turn.OutCourseEntry = OutCourseTeamEntry;

                        _outCourseRunner.Course = WSRunner.CourseName.OUT;
                        _outCourseRunner.Status = WSRunner.RunnerStatus.Ready;
                        _outCourseRunner.Team = OutCourseTeamEntry;
                        _outCourseRunner.Turn = turn;
                        _outCourseRunner.ClearResults();

                        ocRunnerConsole.CurrentTurn = turn;

                        this._presentationWindow.CurrentOutCourseRunnerInfo.Bib = teamInfo.Bib;
                        this._presentationWindow.CurrentOutCourseRunnerInfo.TeamName = teamInfo.Name;
                    }
                    else
                    {
                        OutCourseTeamEntry.ID = -1;
                        OutCourseTeamEntry.TeamID = -1;
                        OutCourseTeamEntry.Bib = null;
                        OutCourseTeamEntry.Name = "";
                        turn.OutCourseEntry = OutCourseTeamEntry;
                        this._presentationWindow.CurrentOutCourseRunnerInfo.Bib = null;
                        this._presentationWindow.CurrentOutCourseRunnerInfo.TeamName = "";
                    }
                    this._presentationWindow.CurrentOutCourseRunnerInfo.RunTime = "";
                    this._presentationWindow.CurrentOutCourseRunnerInfo.Point = "";
                    this._presentationWindow.OutCourseRunnerStatus.ResetClearedMarks();

                    _currentRaceState = RaceState.NotReady;
                    if (_switchLightStatus != null&&switchLightStatusNotifier!=null)
                    {
                        switchLightStatusNotifier.Reset();
                        switchLightStatusNotifier.Update(_switchLightStatus);
                    }
                    if (turnNo >= 0)
                    {
                        _currentRaceState = RaceState.Ready;
                        if (_switchLightStatus != null&&switchLightStatusNotifier!=null)
                        {
                            _switchLightStatus.StartSwitch = true;
                            switchLightStatusNotifier.Update(_switchLightStatus);
                        }
                    }
                    this.buttonCancel.IsEnabled = true;
                    // チーム名表示アニメーション開始
                    _presentationWindow.ShowTeamNameAnimation(InCourseTeamEntry.Name, OutCourseTeamEntry.Name, turnNo, CurrentRound.No);
                }
                else
                {
                    this.buttonEnd.IsEnabled = true;
                }
                this.buttonTurnAgain.IsEnabled = false;
                this.buttonTurnLast.IsEnabled = false;
            }
            rm.Close();

            _presentationWindow.ResetPresentation();
   //         _presentationWindow.MainControl.InCourseRunner.TimeCounter.ResetCounter();
   //         _presentationWindow.MainControl.OutCourseRunner.TimeCounter.ResetCounter();
   //         _presentationWindow.MainControl.ResetTimerCounter();
            this.buttonNext.IsEnabled = false;
            buttonBack.IsEnabled = false;
            ButtonMoveTurn.IsEnabled = false;
            CheckBoxMoveTurnIsLast.IsEnabled = false;

            icRunnerConsole.ResetDifficltPointStatus();
            ocRunnerConsole.ResetDifficltPointStatus();
        }

        private void buttonEnd_Click(object sender, RoutedEventArgs e)
        {
            this._presentationWindow.MainTimerCounter.Stop();
            _currentRaceState = RaceState.NotReady;
            var rm = new ETRoboConRM.ETRoboConRaceMgmtClient();
            //            using (WSRaceMgmt.RaceMgmt rm = new ETRobocon.RaceTraking.GameManagement.WSRaceMgmt.RaceMgmt())
            {
                rm.EndRound(CurrentRound.ID);// (new Guid(CurrentRound.ID));
                this.buttonEnd.IsEnabled = false;
                //   _ownerWindow.Hide();
            }
            rm.Close();

        }

        private void buttonTurnDone_Click(object sender, RoutedEventArgs e)
        {
            _presentationWindow.MainTimerCounter.Stop();
            _presentationWindow.ResetTimerCounter();
            if (_inCourseRunner.Team.ID != -1)
            {
                icRunnerConsole.PostRunResult();
            }
            //            if (!String.IsNullOrEmpty(_outCourseRunner.Team.ID))
            if (_outCourseRunner.Team.ID != -1)
            {
                ocRunnerConsole.PostRunResult();
            }

            _currentRaceState = RaceState.NotReady;
            this.buttonNext.IsEnabled = true;
            this.buttonTurnDone.IsEnabled = false;
            buttonBack.IsEnabled = true;
            ButtonMoveTurn.IsEnabled = false;
            CheckBoxMoveTurnIsLast.IsEnabled = false;
            buttonCancel.IsEnabled = false;

            return;

            
        }

        private int NotifyRaceResult(ETRoboConTrakingSystem.ETRoboConRM.ETRoboConRaceMgmtClient rm, WSRunner runner)
        {
            WSTurn turn = this.Resources["currentTurn"] as WSTurn;
            int point;
            //            WSRaceMgmt.RunnerStatus resultType = WSRaceMgmt.RunnerStatus.COMPLETED;
            ETRoboConTrakingSystem.ETRoboConRM.RunnerStatus resultType = ETRoboConTrakingSystem.ETRoboConRM.RunnerStatus.COMPLETED;
            if (runner.Status.CompareTo(WSRunner.RunnerStatus.Retired) == 0)
            {
                resultType = ETRoboConTrakingSystem.ETRoboConRM.RunnerStatus.RETIRED;// WSRaceMgmt.RunnerStatus.RETIRED;
            }
            List<int> bonusResults = new List<int>();
            foreach (var br in runner.BonusResults)
            {
                if (br.Cleared)
                {
                    bonusResults.Add(br.Spec.ID);
                }
            }
            rm.NotifyRaceResult(out point, turn.ID, runner.Team.ID, resultType, runner.RunTime, bonusResults.ToArray());// new Guid(turn.ID), new Guid(runner.Team.ID), resultType, runner.RunTime, bonusResults.ToArray(), out point);

            return point;
        }

        private void buttonTurnAgain_Click(object sender, RoutedEventArgs e)
        {
            WSRunner obstructedRunner = NotifyObstructed(true);
            
            _inCourseRunner.ClearResults();
            _outCourseRunner.ClearResults();

            if (obstructedRunner!=null)
            {
                obstructedRunner.Status = WSRunner.RunnerStatus.Obstructed;
                this.buttonTurnLast.IsEnabled = false;
                this.buttonNext.IsEnabled = true;
                this.buttonTurnAgain.IsEnabled = false;
                cbObstructedOperation.IsEnabled = false;
                cbObstructedOperation.IsChecked = false;
            }
            _currentRaceState = RaceState.Ready;
        }

        private WSRunner NotifyObstructed(bool retryNow)
        {
            WSRunner obstructedRunner = null;
            if (_inCourseRunner.Status.CompareTo(WSRunner.RunnerStatus.Obstructed) == 0)
            {
                obstructedRunner = _inCourseRunner;
            }
            else if (_outCourseRunner.Status.CompareTo(WSRunner.RunnerStatus.Obstructed) == 0)
            {
                obstructedRunner = _outCourseRunner;
            }
            if (obstructedRunner != null)
            {
                this.buttonTurnLast.IsEnabled = true;
                this.buttonTurnAgain.IsEnabled = true;
                this.buttonTurnDone.IsEnabled = false;
                var rm = new ETRoboConRM.ETRoboConRaceMgmtClient();
                //                using (WSRaceMgmt.RaceMgmt rm = new ETRobocon.RaceTraking.GameManagement.WSRaceMgmt.RaceMgmt())
                {
                    WSTurn turn = this.Resources["currentTurn"] as WSTurn;
                    rm.NotifyObstructed(turn.ID, obstructedRunner.Team.ID, retryNow);// new Guid(turn.ID), new Guid(obstructedRunner.Team.ID), retryNow);
                }
                rm.Close();
            }
            return obstructedRunner;
        }

        private void buttonTurnLast_Click(object sender, RoutedEventArgs e)
        {
            WSRunner obstructedRunner = NotifyObstructed(false);
            _inCourseRunner.ClearResults();
            _outCourseRunner.ClearResults();

            if (obstructedRunner !=null)
            {
                obstructedRunner.Status = WSRunner.RunnerStatus.Obstructed;
                this.buttonTurnAgain.IsEnabled = false;
                this.buttonTurnLast.IsEnabled = false;
                this.buttonNext.IsEnabled = true;
                cbObstructedOperation.IsEnabled = false;
                cbObstructedOperation.IsChecked = false;
            }
        }

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            this._presentationWindow.MainTimerCounter.Start();
            _currentRaceState = RaceState.Running;
            if (_inCourseRunner.Status == WSRunner.RunnerStatus.Ready)
            {
                _inCourseRunner.Status = WSRunner.RunnerStatus.Running;
            }
            if (_outCourseRunner.Status == WSRunner.RunnerStatus.Ready)
            {
                _outCourseRunner.Status = WSRunner.RunnerStatus.Running;
            }
        }

        public void NotifyRunningStart()
        {
            if (_currentRaceState == RaceState.Ready)
            {
                this._presentationWindow.MainTimerCounter.Start();
                _currentRaceState = RaceState.Running;
                if (_switchLightStatus!=null) {
                    _switchLightStatus.StartSwitch=false;
                    _switchLightStatus.ResetSwitch=true;
                }
                if (_inCourseRunner.Status == WSRunner.RunnerStatus.Ready)
                {
                    this._presentationWindow.InCourseRunnerStatus.RunnerTimerCounter.Start();
                    _inCourseRunner.Status = WSRunner.RunnerStatus.Running;
                    if (_switchLightStatus != null)
                    {
                        _switchLightStatus.GoalInSwitch = true;
                        _switchLightStatus.RetireInSwitch = true;
                    }
                }
                if (_outCourseRunner.Status == WSRunner.RunnerStatus.Ready)
                {
                    this._presentationWindow.OutCourseRunnerStatus.RunnerTimerCounter.Start();
                    _outCourseRunner.Status = WSRunner.RunnerStatus.Running;
                    if (_switchLightStatus != null)
                    {
                        _switchLightStatus.GoalOutSwitch = true;
                        _switchLightStatus.RetireOutSwitch = true;
                    }

                }
                if (_switchLightStatus != null && switchLightStatusNotifier!=null)
                {
                    switchLightStatusNotifier.Update(_switchLightStatus);
                }
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { this.ButtonVoice, false });
//                this.ButtonVoice.IsEnabled = false;
                this.Dispatcher.BeginInvoke(new ShowDriftCourseDelegate(ShowDriftCourse));

            }
        }

        private delegate void ShowDriftCourseDelegate();

        private void ShowDriftCourse()
        {
            if (this.CheckBoxSpecialNotify.IsEnabled)
            {
                var commands = new Dictionary<string, string>();
                commands.Add("course", "out");
                string driftCourse = "";
                var random = new Random();
                int r = random.Next(10);
                if (r < 5)
                {
                    driftCourse = "course-a";
                }
                else
                {
                    driftCourse = "course-b";
                }
                commands.Add("drift-turn", driftCourse);
                this.icRunnerConsole.SetSpecialNotice(driftCourse);
                this._presentationWindow.NotifyCommands(commands);
            }
        }

        private delegate void ButtonEnableChangeDelegater(Button button, bool status);
        private void ChangeButtonEnabledStatus(Button button, bool status)
        {
            button.IsEnabled = status;
        }

        public void NotifyRunningStop()
        {
            if (_currentRaceState == RaceState.Running)
            {
                this._presentationWindow.MainTimerCounter.Stop();
                if (_inCourseRunner.Status == WSRunner.RunnerStatus.Running)
                {
                    _presentationWindow.InCourseRunnerStatus.RunnerTimerCounter.Stop();
                    _inCourseRunner.Status = WSRunner.RunnerStatus.Ready;
                    if (_switchLightStatus != null)
                    {
                        _switchLightStatus.GoalInSwitch = false;
                        this._presentationWindow.MainTimerCounter.Stop();
                        _switchLightStatus.RetireInSwitch = false;
                    }
                }
                if (_outCourseRunner.Status == WSRunner.RunnerStatus.Running)
                {
                    _outCourseRunner.Status = WSRunner.RunnerStatus.Ready;
                    _presentationWindow.OutCourseRunnerStatus.RunnerTimerCounter.Stop();
                    if (_switchLightStatus != null)
                    {
                        _switchLightStatus.GoalOutSwitch = false;
                        _switchLightStatus.RetireOutSwitch = false;
                    }
                }
                if (_switchLightStatus != null && switchLightStatusNotifier!=null)
                {
                    _switchLightStatus.ResetSwitch = false;
                    switchLightStatusNotifier.Update(_switchLightStatus);
                }
                _currentRaceState = RaceState.NotReady;
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] {buttonNext,true });
//                this.buttonNext.IsEnabled = true;
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonTurnDone, true });
  //              this.buttonTurnDone.IsEnabled = true;
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonTurnAgain, true });
    //            this.buttonTurnAgain.IsEnabled = true;
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonTurnLast, true });
      //          this.buttonTurnLast.IsEnabled = true;
            }
        }

        public void NotifyGoaled(WSRunner.CourseName cource, int tick)
        {
            if (cource == WSRunner.CourseName.IN)
            {
                if (_inCourseRunner.Status != WSRunner.RunnerStatus.Running)
                {
                    return;
                }
            }
            else if (cource == WSRunner.CourseName.OUT)
            {
                if (_outCourseRunner.Status != WSRunner.RunnerStatus.Running)
                {
                    return;
                }
            }

            //this._presentationWindow.MainControl.StopTimeCounter();
            RunnerMgmtUserControl runnerMgmt = null;
            if (cource == WSRunner.CourseName.IN)
            {
                runnerMgmt = this.icRunnerConsole;
                if (_switchLightStatus != null)
                {
                    if (_inCourseRunner.Status == WSRunner.RunnerStatus.Running)
                    {
                        _switchLightStatus.GoalInSwitch = false;
                        _switchLightStatus.RetireInSwitch = false;
                    }
                }
            }
            else
            {
                runnerMgmt = this.ocRunnerConsole;
                if (_switchLightStatus != null)
                {
                    if (_outCourseRunner.Status == WSRunner.RunnerStatus.Running)
                    {
                        _switchLightStatus.GoalOutSwitch = false;
                        _switchLightStatus.RetireOutSwitch = false;
                    }
                }
            }
            runnerMgmt.NotifyGoaled(tick);

            // 2011年はタイムトライアル後に難所のクリアにチャレンジする
            // タイムトライアル終了時にゴールボタンがクリックされるので、
            // メインのタイマーは、イン、アウト両方がゴールしても、二分経つまで止まってはいけない
            // タイマーをとめないように変更以外にも状態の変更をきちんと考慮する必要がある
            if (_inCourseRunner.Status != WSRunner.RunnerStatus.Running && _outCourseRunner.Status != WSRunner.RunnerStatus.Running)
            {
                if (_switchLightStatus != null)
                {
                    _switchLightStatus.ResetSwitch = false;
                }
                _currentRaceState = RaceState.Finished;
                // 暫定策？多分これだけでよいと思うのだが？
                // インコース、アウトコースともタイムトライアルが済めば、キャンセル不可能
       //         this._presentationWindow.MainTimerCounter.Stop();

                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonTurnDone, true });
//                this.buttonTurnDone.IsEnabled = true;
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonCancel, false });
  //              buttonCancel.IsEnabled = false;
            }
            if (_switchLightStatus != null && switchLightStatusNotifier!=null)
            {
                switchLightStatusNotifier.Update(_switchLightStatus);
            }
        }

        public void NotifyRetired(WSRunner.CourseName cource, int tick)
        {
            if (cource == WSRunner.CourseName.IN)
            {
                if (_inCourseRunner.Status != WSRunner.RunnerStatus.Running)
                {
                    return;
                }
            }
            else if (cource == WSRunner.CourseName.OUT)
            {
                if (_outCourseRunner.Status != WSRunner.RunnerStatus.Running)
                {
                    return;
                }
            }

            RunnerMgmtUserControl runnerMgmt = null;
            if (cource == WSRunner.CourseName.IN)
            {
                runnerMgmt = this.icRunnerConsole;
                if (_switchLightStatus != null&&switchLightStatusNotifier!=null)
                {
                    if (_inCourseRunner.Status == WSRunner.RunnerStatus.Running)
                    {
                        _switchLightStatus.GoalInSwitch = false;
                        _switchLightStatus.RetireInSwitch = false;
                        switchLightStatusNotifier.Update(_switchLightStatus);
                    }
                }
            }
            else
            {
                runnerMgmt = this.ocRunnerConsole;
                if (_outCourseRunner.Status == WSRunner.RunnerStatus.Running)
                {
                    if (_switchLightStatus != null && switchLightStatusNotifier!=null)
                    {
                        _switchLightStatus.GoalOutSwitch = false;
                        _switchLightStatus.RetireOutSwitch = false;
                        switchLightStatusNotifier.Update(_switchLightStatus);
                    }
                }
            }
            runnerMgmt.NotifyRetired(tick);
            if (_inCourseRunner.Status != WSRunner.RunnerStatus.Running && _outCourseRunner.Status != WSRunner.RunnerStatus.Running)
            {
                if (_inCourseRunner.Status == WSRunner.RunnerStatus.Retired && _outCourseRunner.Status == WSRunner.RunnerStatus.Retired)
                {
                    this._presentationWindow.MainTimerCounter.Stop();
                }
                _currentRaceState = RaceState.Finished;
                if (_switchLightStatus != null && switchLightStatusNotifier!=null)
                {
                    _switchLightStatus.ResetSwitch = false;
                    switchLightStatusNotifier.Update(_switchLightStatus);
                }
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonTurnDone, true });
                this.Dispatcher.BeginInvoke(new ButtonEnableChangeDelegater(ChangeButtonEnabledStatus), new object[] { buttonCancel, true });
                //                this.buttonTurnDone.IsEnabled = true;
  //              this.buttonCancel.IsEnabled = false;
            }
        }

        public void UpdateButtonsEnableStatus(bool buttonNextEnable, bool buttonEndEnable, bool buttonDoneEnable, bool buttonAgainEnable, bool buttonLastEnable)
        {
            this.buttonNext.IsEnabled = buttonNextEnable;
            this.buttonEnd.IsEnabled = buttonEndEnable;
            this.buttonTurnDone.IsEnabled = buttonDoneEnable;
            this.buttonTurnAgain.IsEnabled = buttonAgainEnable;
            this.buttonTurnLast.IsEnabled = buttonLastEnable;
        }

        public void ResetButtons()
        {
            buttonNext.IsEnabled = true;
            buttonEnd.IsEnabled = false;
            buttonTurnDone.IsEnabled = false;
            buttonTurnAgain.IsEnabled = false;
            buttonTurnLast.IsEnabled = false;
            buttonBack.IsEnabled = false;
            ButtonMoveTurn.IsEnabled = false;
            CheckBoxMoveTurnIsLast.IsEnabled = false;
            buttonCancel.IsEnabled = false;

            _inCourseRunner.ClearResults();
            _outCourseRunner.ClearResults();

        }

        private void buttonBack_Click(object sender, RoutedEventArgs e)
        {
            var rm = new ETRoboConRM.ETRoboConRaceMgmtClient();
//            using (WSRaceMgmt.RaceMgmt rm = new WSRaceMgmt.RaceMgmt())
            {
                if (MessageBox.Show("ターンを戻しますか?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    if (rm.RollbackTurn(this.CurrentRound.ID))// (new Guid(this.CurrentRound.ID)))
                    {
                        MessageBox.Show("ターンを一つ戻しました");
                        buttonBack.IsEnabled = false;
                    }
                    else
                    {
                        MessageBox.Show("ターンを戻せませんでした");
                    }
                }
            }
            rm.Close();
        }

        private void buttonCancel_Click(object sender, RoutedEventArgs e)
        {
            if (_currentRaceState == RaceState.Running)
            {
                if (MessageBox.Show("スイッチボックスによる時間計測をキャンセルしますか？", "confirmation", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    NotifyRunningStop();
                    buttonCancel.IsEnabled = false;
                }
            }
            else if (_currentRaceState == RaceState.Ready)
            {
                _currentRaceState = RaceState.NotReady;
                this.buttonNext.IsEnabled = true;
                buttonCancel.IsEnabled = false;
                buttonBack.IsEnabled = true;
                ButtonMoveTurn.IsEnabled = true;
                CheckBoxMoveTurnIsLast.IsEnabled = true;
            }
            if (_switchLightStatus != null && switchLightStatusNotifier!=null)
            {
                switchLightStatusNotifier.Reset();
                switchLightStatusNotifier.Update(_switchLightStatus);
            }

        }

        private void ButtonVoice_Click(object sender, RoutedEventArgs e)
        {
            this.Sound321Go.Position = new TimeSpan(0);
            this.Sound321Go.Play();
        }

        private void ButtonMoveTurn_Click(object sender, RoutedEventArgs e)
        {
            var rm = new ETRoboConRM.ETRoboConRaceMgmtClient();
            //            using (WSRaceMgmt.RaceMgmt rm = new WSRaceMgmt.RaceMgmt())
            {
                bool isLastMove = false;
                string msg = "ターンを次のターンに移動しますか？";
                if (CheckBoxMoveTurnIsLast.IsChecked.Value)
                {
                    isLastMove = true;
                    msg = "ターンを最後に移動しますか？";
                }
                if (MessageBox.Show(msg, "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    if (rm.MoveCurrentTurnToFollow(this.CurrentRound.ID,isLastMove))
                    {
                        MessageBox.Show("ターンを移動しました");
                        ButtonMoveTurn.IsEnabled = false;
                        CheckBoxMoveTurnIsLast.IsEnabled = false;
                        buttonBack.IsEnabled = false;
                        ButtonVoice.IsEnabled = false;
                    }
                    else
                    {
                        MessageBox.Show("ターンを移動できませんでした");
                    }
                }
            }
            rm.Close();
        }

        private void cbObstructedOperation_Checked(object sender, RoutedEventArgs e)
        {
            ObstructedOperationStart();
        }

        private void ocRunnerConsole_Loaded(object sender, RoutedEventArgs e)
        {

        }

    }
}
